/*
board-games:    An educational framework for board games programming.
    Copyright (C) 2008  Daniel Gutson, FuDePAN
    
    This file is part of board-games.

    board-games is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    board-games is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
*/

#include <iostream>
#include <string>

#include "common_sdk/board.h"

template <class CellType, size_t Rows, size_t Cols>
class BoardPainter
{
    std::ostream& os;
public:
    BoardPainter(std::ostream& os) : os(os) {}
    
    void paint(const Board<CellType, Rows, Cols>& board) const
    {
        paint_top();
        for(size_t r=0; r<Rows-1; ++r) // all but the last
        {
            //paint_row_of_cells(os, board[r]);  //doesn't work in g++ :(
            paint_row_of_cells(r, board);
            paint_horizontal_line(r);
        }
        //paint_row_of_cells(os, board[Rows-1]);  //doesn't work in g++ :(
        paint_row_of_cells(Rows-1, board);
        paint_bottom();
        os << std::endl;
    }

protected:
    std::string
            upper_left,   upper_mid_sep, upper_right,
            left_mid_sep, cross_sep,     right_mid_sep,
            lower_left,   lower_mid_sep, lower_right,

            outer_vert_delim, outer_horiz_delim,
            inner_vert_delim, inner_horiz_delim;

    size_t  cell_height;

    virtual std::string paint_cell(const CellType& cell_value, size_t cell_row) const = 0;
    
    virtual std::string paint_inner_horiz_delim(size_t col) const
    {
        return inner_horiz_delim;
    }

    virtual std::string paint_inner_vert_delim(size_t row) const
    {
        return inner_vert_delim;
    }

    virtual std::string paint_upper_mid_sep(size_t col) const
    {
        return upper_mid_sep;
    }

    virtual std::string paint_lower_mid_sep(size_t col) const
    {
        return lower_mid_sep;
    }

    virtual std::string paint_cross_sep(size_t row, size_t col) const
    {
        return cross_sep;
    }

private:
    void paint_top() const
    {
        os << upper_left;
        for(size_t c=0; c<Cols-1; c++)
            os << outer_horiz_delim << paint_upper_mid_sep(c);
        os << outer_horiz_delim << upper_right << std::endl;
    }

    void paint_row_of_cells(size_t row, const Board<CellType, Rows, Cols>& board) const
    {
        for(size_t row_in_cell=0; row_in_cell < cell_height; ++row_in_cell)
        {
            os << outer_vert_delim;
            for(size_t col=0; col<Cols-1; ++col)
            {
                os << paint_cell(board[row][col], row_in_cell);
                os << paint_inner_vert_delim(col);
            }
            os << paint_cell(board[row][Cols-1], row_in_cell);
            os << outer_vert_delim << std::endl;
        }
    }

    void paint_horizontal_line(size_t row) const
    {
        os << left_mid_sep;
        for(size_t c=0; c<Cols-1; c++)
            os << paint_inner_horiz_delim(row) << paint_cross_sep(row, c);
        os << paint_inner_horiz_delim(row) << right_mid_sep << std::endl;
    }

    void paint_bottom() const
    {
        os << lower_left;
        for(size_t c=0; c<Cols-1; c++)
            os << outer_horiz_delim << paint_lower_mid_sep(c);
        os << outer_horiz_delim << lower_right << std::endl;
    }
};

